<?php

namespace App\Http\Middleware;

use App\Menu;
use Closure;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\View;
use Illuminate\Support\Facades\Session;

class CheckRole
{
    protected $RouterMenuId;

    //免验证 不考虑 url 查询参数
    protected $FilterCheckRoleAction = [
        'App\Http\Controllers\AdminAPIController@getAsideData' => true,
        'App\Http\Controllers\AdminAPIController@getListProjectsPageData' => true,
        'App\Http\Controllers\AdminWebController@index' => true,
        'App\Http\Controllers\AdminWebController@login' => true,
        'App\Http\Controllers\AdminAPIController@getLoginError' => true,
        'App\Http\Controllers\API\AuthAPIController@getApplicantUsersPageData' => true,
        'App\Http\Controllers\AdminAPIController@getReviewers'  => true,
        'App\Http\Controllers\AdminAPIController@getManageCommissionerPageData' => true,
        'App\Http\Controllers\RolesController@getManageList' => true,
        'App\Http\Controllers\RolesController@getList' => true,
        'App\Http\Controllers\MenusController@getList' => true,
        'App\Http\Controllers\MenusController@menusTree' => true,
        'App\Http\Controllers\MenusController@getPrimary' => true,
        'App\Http\Controllers\AdminAPIController@getFeedbacks'  => true,
        'App\Http\Controllers\AwardAPIController@getAwardedProjects' => true,
        'App\Http\Controllers\AdminAPIController@getPrepareDefensePageData' => true,
        'App\Http\Controllers\AdminAPIController@getPlanAwardPageData' => true,
        'App\Http\Controllers\AdminAPIController@getReviewerProgress' => true,
        'App\Http\Controllers\AdminAPIController@getProjectScoreSegmentsAtExpertReview' => true,
        'App\Http\Controllers\AdminAPIController@getProjects' => true,
        'App\Http\Controllers\AdminAPIController@getReviewerGroups'  => true,
        'App\Http\Controllers\CommonAPIController@getWorkflowPhases' => true,
        'App\Http\Controllers\AdminAPIController@updateReviewerGroupKeywords'   => true,
        'App\Http\Controllers\AdminAPIController@getCandidateReviewers' => true,
        'App\Http\Controllers\AdminAPIController@updateReviewerCanAttendReview' => true,
        'App\Http\Controllers\AdminAPIController@autoReplaceReviewer'   => true,
        'App\Http\Controllers\AdminAPIController@getProjectData'    => true,
        'App\Http\Controllers\AdminAPIController@replaceReviewer'   => true,
        'App\Http\Controllers\AdminAPIController@getMeetingProject' => true
    ];

    //免验证 需考虑 url 查询参数
    protected $FilterCheckRoleURL = [

    ];


    /**
     * Handle an incoming request.
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        //获取用户id
        $user = Auth::user();
        if (empty($user)) {
            return $next($request);
        }

        if ( $user->is_admin == 1 ) {
            //管理员 管理员拥有所有权限
            $Menus = Menu::GetMenusAllKeyData();
            View::share('userMenusKeyData',$Menus);
            return $next($request);
        } elseif ( $user->is_staff == 1){
            //工作人员获取 可访问权限
            $Menus = Menu::getUserMenus($user);
            View::share('userMenusKeyData',$Menus);
        } else {
            //其他账户不允许访问 前往登录页面
           return response()->view('admin.login', ['countOfLoginError' => 0]);
        }

        //获取路由方法
        //如："App\Http\Controllers\AdminWebController@listProjects"
        $route = \Request::route()->getActionName();
        //部分请求不验证
        if (isset($this->FilterCheckRoleAction[$route])) {
            return $next($request);
        }

        $MenusKey = $route;
        //获取url参数
        $urlQuery = $_SERVER['QUERY_STRING'];
        if (!empty($urlQuery)) {
            $MenusKey .= '?'.urldecode($urlQuery);
        }

        //部分url无需验证
        if (isset($this->FilterCheckRoleURL[$MenusKey])) {
            return $next($request);
        }

        try {
            /**
             * @remark
             * @流程：
             * 1.获取二级菜单id "$NowMenuGroupId"
             * 2.获取访问菜单组 "Menu::MenusAllData($NowMenuGroupId);"
             * 3.判断菜单组是否存在当前访问url，当前访问url为二级菜单时 或 本身url未注册时 将不存在
             * 4.获取二级菜单组（$NowMenuGroupId=0），判断是否存在当前url，否则未注册 抛出异常
             */
            $sessionKey = 'NowMenuGroupId';
            //$NowMenuGroupId = (int) session('NowMenuGroupId');
            $NowMenuGroupId = (int) Session::get($sessionKey);
            //判断url是否注册
            $MenusGroup = Menu::MenusAllData($NowMenuGroupId);
            if (isset($MenusGroup[$MenusKey])) {
                $this->RouterMenuId = $MenusGroup[$MenusKey]['id'];
            } else {
                $MenusGroup = Menu::MenusAllData(0);
                if (isset($MenusGroup[$MenusKey])) {
                    $this->RouterMenuId = $MenusGroup[$MenusKey]['id'];
                } else {
                    throw new \Exception('URL 未注册，无法访问');
                }
            }


            //获取用户id
            $user = Auth::user();
            $res = $this->checkUserRole($user);
            if ($res !== true) {
                throw new \Exception('您没有权限执行当前操作，请联系管理员');
            }

            /**
             * 二级菜单时 记录id
            /* 存在不同二级菜单下子菜单 url 相同
            /* 便于区别
             **/
            if ($MenusGroup[$MenusKey]['level'] < 2) {
                //session('NowMenuGroupId',$this->RouterMenuId);
                Session::put($sessionKey,$this->RouterMenuId);
            }
            return $next($request);

        } catch (\Exception $e) {

            return $this->ResError($e->getMessage());
        }
    }

    /**
     * 判断用户是否存在访问当前url权限
     * @param \Illuminate\Contracts\Auth\Authenticatable $user
     * @return bool
     */
    private function checkUserRole(\Illuminate\Contracts\Auth\Authenticatable $user) : bool {
        $Menus = Menu::getUserMenus($user);
        return isset($Menus[$this->RouterMenuId]);
    }

    /**
     * 拒绝访问
     * @param string $err
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
     */
    private function ResError(string $err) {
        if (request()->ajax() || request()->expectsJson()) {
            $result = [
                'ok'  => false,
                'msg' => $err
            ];
            return response()->json($result,200);
        } else {
            return response()->view('404',['tip' => $err]);
        }
    }
}
